<?php

/**
 * @author      :   DungCV
 * @name        :   Fpt_Acl
 * @version     :   201103
 * @copyright   :   My company
 * @todo        :   Using to permission
 */
class My_Acl extends Zend_Acl {

    /**
     * @var Core_Services_Acl
     */
    private static $_instance = null;

    /**
     * @return My_Acl
     */
    public static function getInstance() {
        if (null == self::$_instance) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    private function __construct() {
        $this->_buildResources();
        $this->_buildRules();
    }

    /**
     * Create the resources
     */
    private function _buildResources() {
        $resourceInstance = Resource::getInstance();
        $resources = $resourceInstance->getList();

        if (0 == count($resources)) {
            return;
        }

        $allResources = array();
                
        $numResources = count($resources);
        $i = 0;
        while ($numResources > $i) {
            foreach ($resources as $row) {
                /**
                 * Check if parent resource (if any) exists
                 * Only add if this resource hasn't yet been added and its parent is known, if any
                 */
                $resId = trim(strtolower($row['module_name'] . ':' . $row['controller_name']));

                if (!$this->has($resId)) {
                    $this->addResource(new Zend_Acl_Resource($resId));
                    $i++;
                }
            }
        }
    }

    /**
     * Create rules
     */
    private function _buildRules() {
        $permissionInstance = Permission::getInstance();
        $resouceInstance = Resource::getInstance();
        $privilegeInstance = Privilege::getInstance();

        $permissions = $permissionInstance->getList();
        if (count($permissions) > 0) {
            foreach ($permissions as $row) {
                $roleId = $this->_formatRole($row['group_id']);
                $resource = $resouceInstance->getDetailByID($row['resource_id']);
                $privilege = $privilegeInstance->getDetailByID($row['privilege_id']);
                $resId =  trim(strtolower($resource['module_name'].':'.$resource['controller_name']));                
                if (!$this->hasRole($roleId)) {
                    $this->addRole(new Zend_Acl_Role($roleId));
                }
                if ($row['is_allowed'] == true) {
                    $this->allow($roleId, $resId, trim(strtolower($privilege['action_name'])));
                } else {
                    $this->deny($roleId, $resId, trim(strtolower($privilege['action_name'])));
                }
            }
        }
    }

    public function isUserOrRoleAllowed($roleId, $userId, $module, $controller, $action = null) {
        if ($action != null) {
            $action = strtolower($action);
        }
        $resource = strtolower($module . ':' . $controller);

        /**
         * If the resource don't exist
         */
        if (!$this->has($resource)) {
            return false;
        }

        $roleId = $this->_formatRole($roleId);
        if ($this->hasRole($roleId) && $this->isAllowed($roleId, $resource, $action)) {
            return true;
        }
        return false;
    }

    /**
     * @param array $searchRoles
     * @return bool
     */
    private function _hasAllRolesOf($searchRoles) {
        foreach ($searchRoles as $role) {
            if (!$this->hasRole($role)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Generate the role name which will be added to ACL based on the original role Id
     *
     * @param string $roleId The role Id
     * @return string
     */
    private function _formatRole($roleId) {
        return 'role_' . $roleId;
    }

}
